package com.example.pt.controller;

import com.example.pt.util.BencodingUtils;
import com.example.pt.utils.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/torrent")
@CrossOrigin(origins = "*")
public class TorrentController {

    private static final Logger logger = LoggerFactory.getLogger(TorrentController.class);
    private static final String TRACKER_URL = "http://172.20.10.11:6969/announce";

    /**
     * 处理种子文件，替换passkey为指定用户的passkey
     * 适用于做种者自己使用，不需要用户B实际下载
     * 
     * @param torrentFile 上传的种子文件
     * @param userId 要替换的用户ID (B的用户ID)
     * @return 处理后的种子文件
     */
    @PostMapping("/process")
    public ResponseEntity<Resource> processTorrent(
            @RequestParam("file") MultipartFile torrentFile,
            @RequestParam("userId") Integer userId) {
        
        try {
            logger.info("正在处理种子文件，替换passkey为用户ID: {}", userId);
            
            // 将上传的文件保存到临时文件
            Path tempInputFile = Files.createTempFile("upload_", ".torrent");
            torrentFile.transferTo(tempInputFile.toFile());
            
            logger.info("已保存上传的种子文件到: {}, 大小: {} 字节", 
                tempInputFile, Files.size(tempInputFile));
            
            // 创建输出文件名
            String originalFilename = torrentFile.getOriginalFilename();
            String outputFilename = originalFilename != null ? originalFilename : "processed.torrent";
            if (!outputFilename.toLowerCase().endsWith(".torrent")) {
                outputFilename += ".torrent";
            }
            
            // 去除文件名中的中文字符，避免编码问题
            outputFilename = outputFilename.replaceAll("[^\\x00-\\x7F]", "_");
            
            // 添加用户ID
            String filenameWithoutExt = outputFilename.substring(0, outputFilename.lastIndexOf('.'));
            String ext = outputFilename.substring(outputFilename.lastIndexOf('.'));
            outputFilename = filenameWithoutExt + "_user" + userId + ext;
            
            // 使用工具类修改种子文件，添加passkey
            Path outputPath = Paths.get(System.getProperty("java.io.tmpdir"), outputFilename);
            boolean success = BencodingUtils.updatePasskey(
                tempInputFile.toFile(), outputPath.toFile(), userId.toString());
            
            if (!success) {
                logger.error("处理种子文件失败");
                return ResponseEntity.internalServerError().build();
            }
            
            logger.info("修改后的种子文件已保存: {}, 大小: {} 字节", 
                outputPath, Files.size(outputPath));
            
            // 加载资源
            Resource resource = new UrlResource(outputPath.toUri());
            
            // URL编码文件名，确保不会有编码问题
            String encodedFilename = URLEncoder.encode(outputFilename, StandardCharsets.UTF_8.toString())
                                             .replace("+", "%20");
            
            return ResponseEntity.ok()
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFilename + "\"")
                    .body(resource);
            
        } catch (Exception e) {
            logger.error("处理种子文件异常", e);
            return ResponseEntity.internalServerError().build();
        }
    }
    
    /**
     * 根据本地文件路径处理种子，替换passkey
     */
    @GetMapping("/process-local")
    public ResponseEntity<Resource> processLocalTorrent(
            @RequestParam("filePath") String filePath,
            @RequestParam("userId") Integer userId) {
        
        try {
            logger.info("正在处理本地种子文件: {}, 替换passkey为用户ID: {}", filePath, userId);
            
            // 读取本地种子文件
            File inputFile = new File(filePath);
            if (!inputFile.exists()) {
                logger.error("本地种子文件不存在: {}", filePath);
                return ResponseEntity.notFound().build();
            }
            
            logger.info("本地种子文件大小: {} 字节", inputFile.length());
            
            // 创建输出文件名
            String filename = inputFile.getName();
            // 去除文件名中的中文字符，避免编码问题
            filename = filename.replaceAll("[^\\x00-\\x7F]", "_");
            
            String filenameWithoutExt = filename;
            String ext = "";
            if (filename.toLowerCase().endsWith(".torrent")) {
                filenameWithoutExt = filename.substring(0, filename.lastIndexOf('.'));
                ext = filename.substring(filename.lastIndexOf('.'));
            } else {
                ext = ".torrent";
            }
            
            String outputFilename = filenameWithoutExt + "_user" + userId + ext;
            File outputFile = new File(inputFile.getParent(), outputFilename);
            
            // 使用工具类修改种子文件，添加passkey
            boolean success = BencodingUtils.updatePasskey(inputFile, outputFile, userId.toString());
            
            if (!success) {
                logger.error("处理种子文件失败");
                return ResponseEntity.internalServerError().build();
            }
            
            logger.info("修改后的种子文件已保存: {}, 大小: {} 字节", 
                outputFile.getAbsolutePath(), outputFile.length());
            
            // 加载资源
            Resource resource = new UrlResource(outputFile.toURI());
            
            // URL编码文件名，确保不会有编码问题
            String encodedFilename = URLEncoder.encode(outputFilename, StandardCharsets.UTF_8.toString())
                                             .replace("+", "%20");
            
            return ResponseEntity.ok()
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFilename + "\"")
                    .body(resource);
            
        } catch (Exception e) {
            logger.error("处理种子文件异常", e);
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 上传种子文件 - 设置tracker URL和用户的passkey
     * 用于用户A上传普通种子，将自动设置PT站点tracker和用户A的passkey
     * 
     * @param torrentFile 上传的种子文件
     * @param userId 上传用户的ID（用户A的ID）
     * @return 处理后的种子文件
     */
    @PostMapping("/upload")
    public ResponseEntity<?> uploadTorrent(
            @RequestParam("file") MultipartFile torrentFile,
            @RequestParam("userId") Integer userId) {
        
        try {
            logger.info("用户 {} 正在上传种子文件", userId);
            
            // 将上传的文件保存到临时文件
            Path tempInputFile = Files.createTempFile("upload_", ".torrent");
            torrentFile.transferTo(tempInputFile.toFile());
            
            logger.info("已保存上传的种子文件到: {}, 大小: {} 字节", 
                tempInputFile, Files.size(tempInputFile));
            
            // 创建输出文件名
            String originalFilename = torrentFile.getOriginalFilename();
            String outputFilename = originalFilename != null ? originalFilename : "upload.torrent";
            if (!outputFilename.toLowerCase().endsWith(".torrent")) {
                outputFilename += ".torrent";
            }
            
            // 去除文件名中的中文字符，避免编码问题
            outputFilename = outputFilename.replaceAll("[^\\x00-\\x7F]", "_");
            
            // 添加上传者ID标识
            String filenameWithoutExt = outputFilename.substring(0, outputFilename.lastIndexOf('.'));
            String ext = outputFilename.substring(outputFilename.lastIndexOf('.'));
            outputFilename = filenameWithoutExt + "_uploader" + userId + ext;
            
            // 创建输出文件
            Path outputPath = Paths.get(System.getProperty("java.io.tmpdir"), outputFilename);
            
            // 使用工具类设置种子文件的tracker URL和passkey
            boolean success = BencodingUtils.setTrackerUrl(
                tempInputFile.toFile(), outputPath.toFile(), TRACKER_URL, userId.toString());
            
            if (!success) {
                logger.error("处理上传的种子文件失败");
                return ResponseEntity.ok(Result.fail("处理种子文件失败"));
            }
            
            logger.info("已为上传者(UID:{})设置tracker和passkey，种子文件已保存: {}", 
                userId, outputPath);
            
            // 加载资源
            Resource resource = new UrlResource(outputPath.toUri());
            
            // URL编码文件名
            String encodedFilename = URLEncoder.encode(outputFilename, StandardCharsets.UTF_8.toString())
                                             .replace("+", "%20");
            
            // 如果需要同时返回成功信息和文件，可以先返回成功信息，然后在前端使用URL下载
            Map<String, Object> data = new HashMap<>();
            data.put("fileName", outputFilename);
            data.put("filePath", outputPath.toString());
            data.put("downloadUrl", "/api/torrent/download?path=" + URLEncoder.encode(outputPath.toString(), StandardCharsets.UTF_8.toString()));
            return ResponseEntity.ok(Result.success(data, "种子文件上传成功，已设置tracker和passkey"));
            
        } catch (Exception e) {
            logger.error("上传种子文件异常", e);
            return ResponseEntity.ok(Result.fail("上传种子文件失败: " + e.getMessage()));
        }
    }
    
    /**
     * 下载种子文件 - 替换passkey为下载用户的ID
     * 用于用户B下载种子，将自动替换passkey为用户B的ID
     * 
     * @param filePath 种子文件在服务器上的路径
     * @param userId 下载用户的ID（用户B的ID）
     * @return 处理后的种子文件
     */
    @GetMapping("/download")
    public ResponseEntity<?> downloadTorrent(
            @RequestParam("path") String filePath,
            @RequestParam("userId") Integer userId) {
        
        try {
            logger.info("用户 {} 正在下载种子文件: {}", userId, filePath);
            
            // 读取源文件
            File inputFile = new File(filePath);
            if (!inputFile.exists()) {
                logger.error("种子文件不存在: {}", filePath);
                return ResponseEntity.ok(Result.fail("种子文件不存在"));
            }
            
            // 创建输出文件名
            String filename = inputFile.getName();
            String filenameWithoutExt = filename;
            String ext = ".torrent";
            
            if (filename.contains(".")) {
                filenameWithoutExt = filename.substring(0, filename.lastIndexOf('.'));
                ext = filename.substring(filename.lastIndexOf('.'));
            }
            
            // 添加下载者ID标识
            String outputFilename = filenameWithoutExt + "_downloader" + userId + ext;
            Path outputPath = Paths.get(System.getProperty("java.io.tmpdir"), outputFilename);
            
            // 使用工具类修改种子文件，替换passkey为下载用户的ID
            boolean success = BencodingUtils.updatePasskey(
                inputFile, outputPath.toFile(), userId.toString());
            
            if (!success) {
                logger.error("处理下载的种子文件失败");
                return ResponseEntity.ok(Result.fail("处理种子文件失败"));
            }
            
            logger.info("已为下载者(UID:{})更新passkey，种子文件已保存: {}", 
                userId, outputPath);
            
            // 加载资源
            Resource resource = new UrlResource(outputPath.toUri());
            
            // URL编码文件名
            String encodedFilename = URLEncoder.encode(outputFilename, StandardCharsets.UTF_8.toString())
                                             .replace("+", "%20");
            
            return ResponseEntity.ok()
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFilename + "\"")
                    .body(resource);
            
        } catch (Exception e) {
            logger.error("下载种子文件异常", e);
            return ResponseEntity.ok(Result.fail("下载种子文件失败: " + e.getMessage()));
        }
    }
    
    /**
     * 获取处理后的种子文件，用于前端Ajax请求
     * 返回种子文件的信息，而不是直接下载文件
     */
    @GetMapping("/info")
    public ResponseEntity<Result<Map<String, Object>>> getTorrentInfo(
            @RequestParam("path") String filePath) {
        
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                return ResponseEntity.ok(Result.fail("种子文件不存在"));
            }
            
            Map<String, Object> fileInfo = new HashMap<>();
            fileInfo.put("fileName", file.getName());
            fileInfo.put("filePath", file.getAbsolutePath());
            fileInfo.put("fileSize", file.length());
            fileInfo.put("lastModified", file.lastModified());
            
            return ResponseEntity.ok(Result.success(fileInfo, "获取种子文件信息成功"));
        } catch (Exception e) {
            logger.error("获取种子文件信息异常", e);
            return ResponseEntity.ok(Result.fail("获取种子文件信息失败: " + e.getMessage()));
        }
    }
} 